package com.himiotech.core.framework.helper.utils;

import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.himiotech.core.framework.config.HimioConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.util.ThreadContext;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 工具类
 *
 * @author wuwenbin
 * @author wuwenbin
 */
@Slf4j
public class HimioUtils {

    /**
     * IP地址查询
     */
    public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
    /**
     * 未知地址
     */
    public static final String UNKNOWN = "XX XX";

    /**
     * 构建map参数，很多地方可能会用到
     *
     * @param keyAndValue
     * @return
     */
    public static Map<String, Object> buildMap(Object... keyAndValue) {
        if (keyAndValue != null) {
            if ((keyAndValue.length & 1) == 0) {
                Map<String, Object> resultMap = new HashMap<>(keyAndValue.length);
                for (int i = 0; i < keyAndValue.length; i = i + 2) {
                    Object key = keyAndValue[i];
                    if (key != null) {
                        resultMap.putIfAbsent(key.toString(), keyAndValue[i + 1]);
                    }
                }
                return resultMap;
            }
        }
        return null;
    }

    /**
     * 停止线程池
     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
     * 如果仍人超時，則強制退出.
     * 另对在shutdown时线程本身被调用中断做了处理.
     *
     * @param pool
     */
    public static void shutdownAndAwaitTermination(ExecutorService pool) {
        if (pool != null && !pool.isShutdown()) {
            pool.shutdown();
            try {
                if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                    pool.shutdownNow();
                    if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                        log.info("Pool did not terminate");
                    }
                }
            } catch (InterruptedException ie) {
                pool.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    /**
     * 获取ip的地理位置
     *
     * @param ip
     * @return
     */
    public static String getRealAddressByIp(String ip) {
        // 内网不查询
        if (NetUtil.isInnerIP(ip)) {
            return "内网IP";
        }
        if (HimioConfig.isAddressEnabledStatic()) {
            try {
                HttpRequest get = HttpUtil.createGet(IP_URL);
                get.form(HimioUtils.buildMap("ip", ip, "json", true));
                get.charset(Charset.forName("GBK"));
                String rspStr = get.execute().body();
                if (StrUtil.isEmpty(rspStr)) {
                    log.error("获取地理位置异常 {}", ip);
                    return UNKNOWN;
                }
                JSONObject obj = JSONUtil.parseObj(rspStr);
                String region = obj.getStr("pro");
                String city = obj.getStr("city");
                return String.format("%s %s", region, city);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("获取地理位置异常 {}", e.getMessage());
            }
        }
        return UNKNOWN;
    }

    /**
     * @param value 待处理内容
     * @return
     * @Description 过滤SQL注入内容
     */
    public static String stripSqlInjection(String value) {
        return (null == value) ? null : value.replaceAll("('.+--)|(--)|(%7C)", "");
    }


    /**
     * 防止多线程情况下 Shiro 获取不到 SecurityManager
     */
    public static void checkShiroSecurityManager() {
        SecurityManager securityManager = ThreadContext.getSecurityManager();
        if (securityManager == null) {
            securityManager = SpringUtils.getBean(DefaultSecurityManager.class);
            ThreadContext.bind(securityManager);
        }
    }
}
